#include<iostream.h>
class SubKey{                       //定义子密钥为一个类
public:
 int key[8][6];
}subkey[16];                        //定义子密钥对象数组

class DES{
 int encipher_decipher;                //判断加密还是解密
 int key_in[8][8];                     //用户原始输入的64位二进制数
 int key_out[8][7];                    //除去每行的最后一位校验位
 int c0_d0[8][7];                      //存储经PC-1转换后的56位数据
 int c0[4][7],d0[4][7];                //分别存储c0,d0
    int text[8][8];                       //64位明文
 int text_ip[8][8];                    //经IP转换过后的明文 
 int A[4][8],B[4][8];                  //A,B分别存储经IP转换过后明文的两部分,便于交换
 int temp[8][6];                       //存储经扩展置换后的48位二进制值
 int temp1[8][6];                      //存储和子密钥异或后的结果
 int s_result[8][4];                   //存储经S变换后的32位值
 int text_p[8][4];                     //经P置换后的32位结果
 int secret_ip[8][8];                  //经逆IP转换后的密文
public:
 void Key_Putting();
 void PC_1();
 int function(int,int);    //异或
 void SubKey_Production();
    void IP_Convert();
 void f();        
 void _IP_Convert();              
 void Out_secret();
};
void DES::Key_Putting()           //得到密钥中对算法有用的56位
{
 cout<<"请输入64位的密钥(8行8列且每行都得有奇数个1):\n";
 for(int i=0;i<8;i++)
  for(int j=0;j<8;j++){
   cin>>key_in[i][j];
   if(j!=7) key_out[i][j]=key_in[i][j];
  }
}
void DES::PC_1()                       //PC-1置换函数
{
 int pc_1[8][7]={                          //PC-1
  {57, 49, 41, 33, 25, 17, 9},
  {1, 58, 50, 42, 34, 26, 18},
  {10,  2, 59, 51, 43, 35, 27},
  {19, 11,  3, 60, 52, 44, 36},
  {63, 55, 47, 39, 31, 23, 15},
  {7, 62, 54, 46, 38, 30, 22},
  {14,  6, 61, 53, 45, 37, 29},
  {21, 13,  5, 28, 20, 12,  4}
 };
 int i,j;
 for(i=0;i<8;i++)
  for(j=0;j<7;j++)
   c0_d0[i][j]=key_out[ (pc_1[i][j]-1)/8 ][ (pc_1[i][j]-1)%8 ];
}
int DES::function(int a,int b)    //模拟二进制数的异或运算,a和b为整型的0和1,返回值为整型的0或1
{
 if(a!=b)return 1;
 else return 0;
}
void DES::SubKey_Production()            //生成子密钥
{
 int move[16][2]={       //循环左移的位数
  1 , 1 , 2 , 1 ,
  3 , 2 , 4 , 2 ,
  5 , 2 , 6 , 2 ,
  7 , 2 , 8 , 2 ,
  9 , 1, 10 , 2,
  11 , 2, 12 , 2,
  13 , 2, 14 , 2,
  15 , 2, 16 , 1
 };
 int pc_2[8][6]={                       //PC-2
  14, 17 ,11 ,24 , 1 , 5,
  3 ,28 ,15 , 6 ,21 ,10,
  23, 19, 12,  4, 26,  8,
  16, 7, 27, 20 ,13 , 2,
  41, 52, 31, 37, 47, 55,
  30, 40, 51, 45, 33, 48,
  44, 49, 39, 56, 34, 53,
  46, 42, 50, 36, 29, 32
 };
 for(int i=0;i<16;i++)     //生成子密钥
 {
  int j,k;
  int a[2],b[2];    
  int bb[28],cc[28];
  for(j=0;j<4;j++)
   for(k=0;k<7;k++)
    c0[j][k]=c0_d0[j][k];
  for(j=4;j<8;j++)
   for(k=0;k<7;k++)
    d0[j-4][k]=c0_d0[j][k];
  for(j=0;j<4;j++)  
   for(k=0;k<7;k++){
    bb[7*j+k]=c0[j][k];
    cc[7*j+k]=d0[j][k];
   }
  for(j=0;j<move[i][1];j++){
   a[j]=bb[j];
   b[j]=cc[j];
  }
  for(j=0;j<28-move[i][1];j++){
   bb[j]=bb[j+1];
   cc[j]=cc[j+1];
  }
  for(j=0;j<move[i][1];j++){
   bb[27-j]=a[j];
   cc[27-j]=b[j];
  }
  for(j=0;j<28;j++){
   c0[j/7][j%7]=bb[j];
   d0[j/7][j%7]=cc[j];
  }
  for(j=0;j<4;j++)          //L123--L128是把c0,d0合并成c0_d0
   for(k=0;k<7;k++)
    c0_d0[j][k]=c0[j][k];
  for(j=4;j<8;j++)
   for(k=0;k<7;k++)
    c0_d0[j][k]=d0[j-4][k];
  for(j=0;j<8;j++)          //对Ci,Di进行PC-2置换
   for(k=0;k<6;k++)
    subkey[i].key[j][k]=c0_d0[  (pc_2[j][k]-1)/7  ][  (pc_2[j][k]-1)%7  ];
 }
}
void DES::IP_Convert()
{
 int IP[8][8]={               //初始置换IP矩阵
  58, 50, 42, 34, 26, 18, 10,  2,
  60, 52, 44, 36, 28, 20, 12,  4,
  62, 54, 46, 38, 30, 22, 14,  6,
  64, 56, 48, 40, 32, 24, 16,  8,
  57, 49, 41, 33, 25, 17,  9,  1,
  59, 51, 43, 35, 27, 19, 11,  3,
  61, 53, 45, 37, 29, 21, 13,  5,
  63, 55, 47, 39, 31, 23, 15,  7
 };
 cout<<"你好,你要加密还是解密?加密请按1号键(输入1),解密请按2号键,并确定."<<'\n';
 cin>>encipher_decipher;
 char * s;
    if(encipher_decipher==1) s="明文";
 else  s="密文";
 cout<<"请输入64位"<<s<<"(二进制):\n";
 int i,j;
 for(i=0;i<8;i++)
  for(j=0;j<8;j++)
   cin>>text[i][j];
    for(i=0;i<8;i++)                          //进行IP变换
  for(j=0;j<8;j++)
   text_ip[i][j]=text[  (IP[i][j]-1)/8  ][  (IP[i][j]-1)%8  ];
}
